using System;
using System.Reflection;
using Deepcode.Flux.Core.Extensions.Codons;

namespace Deepcode.Flux.Core.Extensions
{
	/// <summary>
	/// Represents a single builder object that will create a codon object
	/// based on the requested tag name.
	/// </summary>
	public class CodonBuilder
	{
		private string _ClassName;
		private string _TagName;
		/// <summary>
		/// Create a builder for a codon. The classname is the classname of the codon,
		/// it is instantiated and it's tagname retreived from the attributes.
		/// </summary>
		/// <param name="className"></param>
		public CodonBuilder( string ClassName  )
		{
			this._ClassName = ClassName;
			// Get the object of the type
			Type codonType = Type.GetType( this._ClassName );
			if( codonType == null )
				throw new Exception("Codon Builder initialisation for " + ClassName + " failed as it could not get the type.");

			XmlCodonNameAttribute codonTagName = (XmlCodonNameAttribute) Attribute.GetCustomAttribute( codonType, typeof( XmlCodonNameAttribute ));
			if( codonTagName == null )
				throw new Exception("Codon class " + this._ClassName + " does not have an XmlCodonName attribute specifeid.");

			_TagName = codonTagName.Name;
		}
		/// <summary>
		/// Returns the tagname that this builder will process
		/// </summary>
		public string TagName
		{
			get
			{
				return _TagName;
			}
		}
		/// <summary>
		/// Returns the className the name of the addintag class
		/// </summary>
		public string ClassName 
		{
			get 
			{
				return _ClassName;
			}
		}
		/// <summary>
		/// Creates and returns a new codon
		/// </summary>
		public ICodon BuildCodon()
		{
			ICodon codon = null;
			try
			{
				// Get a reference to the object type
				Type classType = Type.GetType( ClassName );
				// Invoke it's default constructor
				object o = classType.GetConstructor( new Type[0] ).Invoke( new object [0] );
				if( o != null )
					if( o is ICodon ) codon = (ICodon) o;
			}
			catch{ codon = null; }
			return codon;
		}
	}
}
